home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / Miro_Downloader.exe / BitTorrent / StorageWrapper.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2007-11-12  |  18.8 KB  |  684 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. from sha import sha
  5. from threading import Event
  6. from bitfield import Bitfield
  7.  
  8. def dummy_status(fractionDone = None, activity = None):
  9.     pass
  10.  
  11.  
  12. def dummy_data_flunked(size):
  13.     pass
  14.  
  15.  
  16. def dummy_hash_skip_func(block):
  17.     return False
  18.  
  19.  
  20. class StorageWrapper:
  21.     
  22.     def __init__(self, storage, request_size, hashes, piece_size, finished, failed, statusfunc = dummy_status, flag = Event(), check_hashes = True, data_flunked = dummy_data_flunked, hash_skip_func = dummy_hash_skip_func):
  23.         self.storage = storage
  24.         self.request_size = request_size
  25.         self.hashes = hashes
  26.         self.piece_size = piece_size
  27.         self.data_flunked = data_flunked
  28.         self.total_length = storage.get_total_length()
  29.         self.amount_left = self.total_length
  30.         if self.total_length <= piece_size * (len(hashes) - 1):
  31.             raise ValueError, 'bad data from tracker - total too small'
  32.         
  33.         if self.total_length > piece_size * len(hashes):
  34.             raise ValueError, 'bad data from tracker - total too big'
  35.         
  36.         self.finished = finished
  37.         self.failed = failed
  38.         self.numactive = [
  39.             0] * len(hashes)
  40.         self.inactive_requests = [
  41.             1] * len(hashes)
  42.         self.amount_inactive = self.total_length
  43.         self.endgame = False
  44.         self.have = Bitfield(len(hashes))
  45.         self.waschecked = [
  46.             check_hashes] * len(hashes)
  47.         self.places = { }
  48.         self.holes = []
  49.         if len(hashes) == 0:
  50.             finished()
  51.             return None
  52.         
  53.         targets = { }
  54.         total = len(hashes)
  55.         for i in xrange(len(hashes)):
  56.             if not self._waspre(i):
  57.                 targets.setdefault(hashes[i], []).append(i)
  58.                 total -= 1
  59.                 continue
  60.         
  61.         numchecked = 0
  62.         if total and check_hashes:
  63.             statusfunc({
  64.                 'activity': 'checking existing file',
  65.                 'fractionDone': 0 })
  66.         
  67.         
  68.         def markgot(piece, pos, self = self, check_hashes = check_hashes):
  69.             self.places[piece] = pos
  70.             self.have[piece] = True
  71.             self.amount_left -= self._piecelen(piece)
  72.             self.amount_inactive -= self._piecelen(piece)
  73.             self.inactive_requests[piece] = None
  74.             self.waschecked[piece] = check_hashes
  75.  
  76.         lastlen = self._piecelen(len(hashes) - 1)
  77.         for i in xrange(len(hashes)):
  78.             files = self.storage.files_in_range(piece_size * i, self._piecelen(i))
  79.             if not self._waspre(i):
  80.                 self.holes.append(i)
  81.                 continue
  82.             if not check_hashes or hash_skip_func(i, files):
  83.                 markgot(i, i)
  84.                 continue
  85.             sh = sha(self.storage.read(piece_size * i, lastlen))
  86.             sp = sh.digest()
  87.             sh.update(self.storage.read(piece_size * i + lastlen, self._piecelen(i) - lastlen))
  88.             s = sh.digest()
  89.             if s == hashes[i]:
  90.                 markgot(i, i)
  91.             elif targets.get(s) and self._piecelen(i) == self._piecelen(targets[s][-1]):
  92.                 markgot(targets[s].pop(), i)
  93.             elif not self.have[len(hashes) - 1] and sp == hashes[-1]:
  94.                 if i == len(hashes) - 1 or not self._waspre(len(hashes) - 1):
  95.                     markgot(len(hashes) - 1, i)
  96.                 else:
  97.                     self.places[i] = i
  98.             if flag.isSet():
  99.                 return None
  100.             
  101.             numchecked += 1
  102.             statusfunc({
  103.                 'fractionDone': 1 - float(self.amount_left) / self.total_length })
  104.         
  105.         if self.amount_left == 0:
  106.             finished()
  107.         
  108.  
  109.     
  110.     def _waspre(self, piece):
  111.         return self.storage.was_preallocated(piece * self.piece_size, self._piecelen(piece))
  112.  
  113.     
  114.     def _piecelen(self, piece):
  115.         if piece < len(self.hashes) - 1:
  116.             return self.piece_size
  117.         else:
  118.             return self.total_length - piece * self.piece_size
  119.  
  120.     
  121.     def get_amount_left(self):
  122.         return self.amount_left
  123.  
  124.     
  125.     def do_I_have_anything(self):
  126.         return self.amount_left < self.total_length
  127.  
  128.     
  129.     def _make_inactive(self, index):
  130.         length = min(self.piece_size, self.total_length - self.piece_size * index)
  131.         l = []
  132.         x = 0
  133.         while x + self.request_size < length:
  134.             l.append((x, self.request_size))
  135.             x += self.request_size
  136.         l.append((x, length - x))
  137.         self.inactive_requests[index] = l
  138.  
  139.     
  140.     def is_endgame(self):
  141.         return self.endgame
  142.  
  143.     
  144.     def get_have_list(self):
  145.         return self.have.tostring()
  146.  
  147.     
  148.     def do_I_have(self, index):
  149.         return self.have[index]
  150.  
  151.     
  152.     def do_I_have_requests(self, index):
  153.         return not (not self.inactive_requests[index])
  154.  
  155.     
  156.     def new_request(self, index):
  157.         if self.inactive_requests[index] == 1:
  158.             self._make_inactive(index)
  159.         
  160.         self.numactive[index] += 1
  161.         rs = self.inactive_requests[index]
  162.         r = min(rs)
  163.         rs.remove(r)
  164.         self.amount_inactive -= r[1]
  165.         if self.amount_inactive == 0:
  166.             self.endgame = True
  167.         
  168.         return r
  169.  
  170.     
  171.     def piece_came_in(self, index, begin, piece):
  172.         
  173.         try:
  174.             return self._piece_came_in(index, begin, piece)
  175.         except IOError:
  176.             e = None
  177.             self.failed('IO Error ' + str(e))
  178.             return True
  179.  
  180.  
  181.     
  182.     def _piece_came_in(self, index, begin, piece):
  183.         if not self.places.has_key(index):
  184.             n = self.holes.pop(0)
  185.             if self.places.has_key(n):
  186.                 oldpos = self.places[n]
  187.                 old = self.storage.read(self.piece_size * oldpos, self._piecelen(n))
  188.                 if self.have[n] and sha(old).digest() != self.hashes[n]:
  189.                     self.failed('data corrupted on disk - maybe you have two copies running?')
  190.                     return True
  191.                 
  192.                 self.storage.write(self.piece_size * n, old)
  193.                 self.places[n] = n
  194.                 if index == oldpos or index in self.holes:
  195.                     self.places[index] = oldpos
  196.                 else:
  197.                     for p, v in self.places.items():
  198.                         if v == index:
  199.                             break
  200.                             continue
  201.                     
  202.                     self.places[index] = index
  203.                     self.places[p] = oldpos
  204.                     old = self.storage.read(self.piece_size * index, self.piece_size)
  205.                     self.storage.write(self.piece_size * oldpos, old)
  206.             elif index in self.holes or index == n:
  207.                 if not self._waspre(n):
  208.                     self.storage.write(self.piece_size * n, self._piecelen(n) * chr(255))
  209.                 
  210.                 self.places[index] = n
  211.             else:
  212.                 for p, v in self.places.items():
  213.                     if v == index:
  214.                         break
  215.                         continue
  216.                 
  217.                 self.places[index] = index
  218.                 self.places[p] = n
  219.                 old = self.storage.read(self.piece_size * index, self._piecelen(n))
  220.                 self.storage.write(self.piece_size * n, old)
  221.         
  222.         self.storage.write(self.places[index] * self.piece_size + begin, piece)
  223.         self.numactive[index] -= 1
  224.         return True
  225.  
  226.     
  227.     def request_lost(self, index, begin, length):
  228.         self.inactive_requests[index].append((begin, length))
  229.         self.amount_inactive += length
  230.         self.numactive[index] -= 1
  231.  
  232.     
  233.     def get_piece(self, index, begin, length):
  234.         
  235.         try:
  236.             return self._get_piece(index, begin, length)
  237.         except IOError:
  238.             e = None
  239.             self.failed('IO Error ' + str(e))
  240.             return None
  241.  
  242.  
  243.     
  244.     def _get_piece(self, index, begin, length):
  245.         if not self.have[index]:
  246.             return None
  247.         
  248.         if not self.waschecked[index]:
  249.             if sha(self.storage.read(self.piece_size * self.places[index], self._piecelen(index))).digest() != self.hashes[index]:
  250.                 self.failed('told file complete on start-up, but piece failed hash check')
  251.                 return None
  252.             
  253.             self.waschecked[index] = True
  254.         
  255.         if begin + length > self._piecelen(index):
  256.             return None
  257.         
  258.         return self.storage.read(self.piece_size * self.places[index] + begin, length)
  259.  
  260.  
  261.  
  262. class DummyStorage:
  263.     
  264.     def __init__(self, total, pre = False, ranges = []):
  265.         self.pre = pre
  266.         self.ranges = ranges
  267.         self.s = chr(255) * total
  268.         self.done = False
  269.  
  270.     
  271.     def was_preexisting(self):
  272.         return self.pre
  273.  
  274.     
  275.     def was_preallocated(self, begin, length):
  276.         for b, l in self.ranges:
  277.             if begin >= b and begin + length <= b + l:
  278.                 return True
  279.                 continue
  280.         
  281.         return False
  282.  
  283.     
  284.     def get_total_length(self):
  285.         return len(self.s)
  286.  
  287.     
  288.     def read(self, begin, length):
  289.         return self.s[begin:begin + length]
  290.  
  291.     
  292.     def write(self, begin, piece):
  293.         self.s = self.s[:begin] + piece + self.s[begin + len(piece):]
  294.  
  295.     
  296.     def finished(self):
  297.         self.done = True
  298.  
  299.  
  300.  
  301. def test_basic():
  302.     ds = DummyStorage(3)
  303.     sw = StorageWrapper(ds, 2, [
  304.         sha('abc').digest()], 4, ds.finished, None)
  305.     if not sw.get_amount_left() == 3:
  306.         raise AssertionError
  307.     if not not sw.do_I_have_anything():
  308.         raise AssertionError
  309.     if not sw.get_have_list() == chr(0):
  310.         raise AssertionError
  311.     if not sw.do_I_have_requests(0):
  312.         raise AssertionError
  313.     x = []
  314.     x.append(sw.new_request(0))
  315.     if not sw.do_I_have_requests(0):
  316.         raise AssertionError
  317.     x.append(sw.new_request(0))
  318.     if not not sw.do_I_have_requests(0):
  319.         raise AssertionError
  320.     x.sort()
  321.     if not x == [
  322.         (0, 2),
  323.         (2, 1)]:
  324.         raise AssertionError
  325.     sw.request_lost(0, 2, 1)
  326.     del x[-1]
  327.     if not sw.do_I_have_requests(0):
  328.         raise AssertionError
  329.     x.append(sw.new_request(0))
  330.     if not x == [
  331.         (0, 2),
  332.         (2, 1)]:
  333.         raise AssertionError
  334.     if not not sw.do_I_have_requests(0):
  335.         raise AssertionError
  336.     sw.piece_came_in(0, 0, 'ab')
  337.     if not not sw.do_I_have_requests(0):
  338.         raise AssertionError
  339.     if not sw.get_amount_left() == 3:
  340.         raise AssertionError
  341.     if not not sw.do_I_have_anything():
  342.         raise AssertionError
  343.     if not sw.get_have_list() == chr(0):
  344.         raise AssertionError
  345.     if not not (ds.done):
  346.         raise AssertionError
  347.     sw.piece_came_in(0, 2, 'c')
  348.     if not not sw.do_I_have_requests(0):
  349.         raise AssertionError
  350.     if not sw.get_amount_left() == 0:
  351.         raise AssertionError
  352.     if not sw.do_I_have_anything():
  353.         raise AssertionError
  354.     if not sw.get_have_list() == chr(128):
  355.         raise AssertionError
  356.     if not sw.get_piece(0, 0, 3) == 'abc':
  357.         raise AssertionError
  358.     if not sw.get_piece(0, 1, 2) == 'bc':
  359.         raise AssertionError
  360.     if not sw.get_piece(0, 0, 2) == 'ab':
  361.         raise AssertionError
  362.     if not sw.get_piece(0, 1, 1) == 'b':
  363.         raise AssertionError
  364.     if not ds.done:
  365.         raise AssertionError
  366.  
  367.  
  368. def test_two_pieces():
  369.     ds = DummyStorage(4)
  370.     sw = StorageWrapper(ds, 3, [
  371.         sha('abc').digest(),
  372.         sha('d').digest()], 3, ds.finished, None)
  373.     if not sw.get_amount_left() == 4:
  374.         raise AssertionError
  375.     if not not sw.do_I_have_anything():
  376.         raise AssertionError
  377.     if not sw.get_have_list() == chr(0):
  378.         raise AssertionError
  379.     if not sw.do_I_have_requests(0):
  380.         raise AssertionError
  381.     if not sw.do_I_have_requests(1):
  382.         raise AssertionError
  383.     if not sw.new_request(0) == (0, 3):
  384.         raise AssertionError
  385.     if not sw.get_amount_left() == 4:
  386.         raise AssertionError
  387.     if not not sw.do_I_have_anything():
  388.         raise AssertionError
  389.     if not sw.get_have_list() == chr(0):
  390.         raise AssertionError
  391.     if not not sw.do_I_have_requests(0):
  392.         raise AssertionError
  393.     if not sw.do_I_have_requests(1):
  394.         raise AssertionError
  395.     if not sw.new_request(1) == (0, 1):
  396.         raise AssertionError
  397.     if not sw.get_amount_left() == 4:
  398.         raise AssertionError
  399.     if not not sw.do_I_have_anything():
  400.         raise AssertionError
  401.     if not sw.get_have_list() == chr(0):
  402.         raise AssertionError
  403.     if not not sw.do_I_have_requests(0):
  404.         raise AssertionError
  405.     if not not sw.do_I_have_requests(1):
  406.         raise AssertionError
  407.     sw.piece_came_in(0, 0, 'abc')
  408.     if not sw.get_amount_left() == 1:
  409.         raise AssertionError
  410.     if not sw.do_I_have_anything():
  411.         raise AssertionError
  412.     if not sw.get_have_list() == chr(128):
  413.         raise AssertionError
  414.     if not not sw.do_I_have_requests(0):
  415.         raise AssertionError
  416.     if not not sw.do_I_have_requests(1):
  417.         raise AssertionError
  418.     if not sw.get_piece(0, 0, 3) == 'abc':
  419.         raise AssertionError
  420.     if not not (ds.done):
  421.         raise AssertionError
  422.     sw.piece_came_in(1, 0, 'd')
  423.     if not ds.done:
  424.         raise AssertionError
  425.     if not sw.get_amount_left() == 0:
  426.         raise AssertionError
  427.     if not sw.do_I_have_anything():
  428.         raise AssertionError
  429.     if not sw.get_have_list() == chr(192):
  430.         raise AssertionError
  431.     if not not sw.do_I_have_requests(0):
  432.         raise AssertionError
  433.     if not not sw.do_I_have_requests(1):
  434.         raise AssertionError
  435.     if not sw.get_piece(1, 0, 1) == 'd':
  436.         raise AssertionError
  437.  
  438.  
  439. def test_hash_fail():
  440.     ds = DummyStorage(4)
  441.     sw = StorageWrapper(ds, 4, [
  442.         sha('abcd').digest()], 4, ds.finished, None)
  443.     if not sw.get_amount_left() == 4:
  444.         raise AssertionError
  445.     if not not sw.do_I_have_anything():
  446.         raise AssertionError
  447.     if not sw.get_have_list() == chr(0):
  448.         raise AssertionError
  449.     if not sw.do_I_have_requests(0):
  450.         raise AssertionError
  451.     if not sw.new_request(0) == (0, 4):
  452.         raise AssertionError
  453.     sw.piece_came_in(0, 0, 'abcx')
  454.     if not sw.get_amount_left() == 4:
  455.         raise AssertionError
  456.     if not not sw.do_I_have_anything():
  457.         raise AssertionError
  458.     if not sw.get_have_list() == chr(0):
  459.         raise AssertionError
  460.     if not sw.do_I_have_requests(0):
  461.         raise AssertionError
  462.     if not sw.new_request(0) == (0, 4):
  463.         raise AssertionError
  464.     if not not (ds.done):
  465.         raise AssertionError
  466.     sw.piece_came_in(0, 0, 'abcd')
  467.     if not ds.done:
  468.         raise AssertionError
  469.     if not sw.get_amount_left() == 0:
  470.         raise AssertionError
  471.     if not sw.do_I_have_anything():
  472.         raise AssertionError
  473.     if not sw.get_have_list() == chr(128):
  474.         raise AssertionError
  475.     if not not sw.do_I_have_requests(0):
  476.         raise AssertionError
  477.  
  478.  
  479. def test_lazy_hashing():
  480.     ds = DummyStorage(4, ranges = [
  481.         (0, 4)])
  482.     flag = Event()
  483.     sw = StorageWrapper(ds, 4, [
  484.         sha('abcd').digest()], 4, ds.finished, (lambda x, flag = flag: flag.set()), check_hashes = False)
  485.     if not sw.get_piece(0, 0, 2) is None:
  486.         raise AssertionError
  487.     if not flag.isSet():
  488.         raise AssertionError
  489.  
  490.  
  491. def test_lazy_hashing_pass():
  492.     ds = DummyStorage(4)
  493.     flag = Event()
  494.     sw = StorageWrapper(ds, 4, [
  495.         sha(chr(255) * 4).digest()], 4, ds.finished, (lambda x, flag = flag: flag.set()), check_hashes = False)
  496.     if not sw.get_piece(0, 0, 2) is None:
  497.         raise AssertionError
  498.     if not not flag.isSet():
  499.         raise AssertionError
  500.  
  501.  
  502. def test_preexisting():
  503.     ds = DummyStorage(4, True, [
  504.         (0, 4)])
  505.     sw = StorageWrapper(ds, 2, [
  506.         sha(chr(255) * 2).digest(),
  507.         sha('ab').digest()], 2, ds.finished, None)
  508.     if not sw.get_amount_left() == 2:
  509.         raise AssertionError
  510.     if not sw.do_I_have_anything():
  511.         raise AssertionError
  512.     if not sw.get_have_list() == chr(128):
  513.         raise AssertionError
  514.     if not not sw.do_I_have_requests(0):
  515.         raise AssertionError
  516.     if not sw.do_I_have_requests(1):
  517.         raise AssertionError
  518.     if not sw.new_request(1) == (0, 2):
  519.         raise AssertionError
  520.     if not not (ds.done):
  521.         raise AssertionError
  522.     sw.piece_came_in(1, 0, 'ab')
  523.     if not ds.done:
  524.         raise AssertionError
  525.     if not sw.get_amount_left() == 0:
  526.         raise AssertionError
  527.     if not sw.do_I_have_anything():
  528.         raise AssertionError
  529.     if not sw.get_have_list() == chr(192):
  530.         raise AssertionError
  531.     if not not sw.do_I_have_requests(0):
  532.         raise AssertionError
  533.     if not not sw.do_I_have_requests(1):
  534.         raise AssertionError
  535.  
  536.  
  537. def test_total_too_short():
  538.     ds = DummyStorage(4)
  539.     
  540.     try:
  541.         StorageWrapper(ds, 4, [
  542.             sha(chr(255) * 4).digest(),
  543.             sha(chr(255) * 4).digest()], 4, ds.finished, None)
  544.         raise 'fail'
  545.     except ValueError:
  546.         pass
  547.  
  548.  
  549.  
  550. def test_total_too_big():
  551.     ds = DummyStorage(9)
  552.     
  553.     try:
  554.         sw = StorageWrapper(ds, 4, [
  555.             sha('qqqq').digest(),
  556.             sha(chr(255) * 4).digest()], 4, ds.finished, None)
  557.         raise 'fail'
  558.     except ValueError:
  559.         pass
  560.  
  561.  
  562.  
  563. def test_end_above_total_length():
  564.     ds = DummyStorage(3, True)
  565.     sw = StorageWrapper(ds, 4, [
  566.         sha('qqq').digest()], 4, ds.finished, None)
  567.     if not sw.get_piece(0, 0, 4) == None:
  568.         raise AssertionError
  569.  
  570.  
  571. def test_end_past_piece_end():
  572.     ds = DummyStorage(4, True, ranges = [
  573.         (0, 4)])
  574.     sw = StorageWrapper(ds, 4, [
  575.         sha(chr(255) * 2).digest(),
  576.         sha(chr(255) * 2).digest()], 2, ds.finished, None)
  577.     if not ds.done:
  578.         raise AssertionError
  579.     if not sw.get_piece(0, 0, 3) == None:
  580.         raise AssertionError
  581.  
  582. from random import shuffle
  583.  
  584. def test_alloc_random():
  585.     ds = DummyStorage(101)
  586.     sw = 1([], [], [ sha(chr(i)).digest() for i in xrange(101) ], 1, ds.finished, None)
  587.     for i in xrange(100):
  588.         if not sw.new_request(i) == (0, 1):
  589.             raise AssertionError
  590.         ds
  591.     
  592.     r = range(100)
  593.     shuffle(r)
  594.     for i in r:
  595.         sw.piece_came_in(i, 0, chr(i))
  596.     
  597.     for i in xrange(100):
  598.         if not sw.get_piece(i, 0, 1) == chr(i):
  599.             raise AssertionError
  600.         StorageWrapper
  601.     
  602.     if not [] == []([ chr(i) for i in xrange(100) ]):
  603.         raise AssertionError
  604.     ''.join
  605.  
  606.  
  607. def test_alloc_resume():
  608.     ds = DummyStorage(101)
  609.     sw = 1([], [], [ sha(chr(i)).digest() for i in xrange(101) ], 1, ds.finished, None)
  610.     for i in xrange(100):
  611.         if not sw.new_request(i) == (0, 1):
  612.             raise AssertionError
  613.         ds
  614.     
  615.     r = range(100)
  616.     shuffle(r)
  617.     for i in r[:50]:
  618.         sw.piece_came_in(i, 0, chr(i))
  619.     
  620.     if not ds.s[50:] == chr(255) * 51:
  621.         raise AssertionError
  622.     StorageWrapper
  623.     ds.ranges = [
  624.         (0, 50)]
  625.     sw = 1([], [], [ sha(chr(i)).digest() for i in xrange(101) ], 1, ds.finished, None)
  626.     for i in r[50:]:
  627.         sw.piece_came_in(i, 0, chr(i))
  628.     
  629.     if not [] == []([ chr(i) for i in xrange(100) ]):
  630.         raise AssertionError
  631.     ''.join
  632.  
  633.  
  634. def test_last_piece_pre():
  635.     ds = DummyStorage(3, ranges = [
  636.         (2, 1)])
  637.     ds.s = chr(255) + chr(255) + 'c'
  638.     sw = StorageWrapper(ds, 2, [
  639.         sha('ab').digest(),
  640.         sha('c').digest()], 2, ds.finished, None)
  641.     if not not sw.do_I_have_requests(1):
  642.         raise AssertionError
  643.     if not sw.do_I_have_requests(0):
  644.         raise AssertionError
  645.  
  646.  
  647. def test_not_last_pre():
  648.     ds = DummyStorage(3, ranges = [
  649.         (1, 1)])
  650.     ds.s = chr(255) + 'a' + chr(255)
  651.     sw = StorageWrapper(ds, 1, [
  652.         sha('a').digest()] * 3, 1, ds.finished, None)
  653.     if not not sw.do_I_have_requests(1):
  654.         raise AssertionError
  655.     if not sw.do_I_have_requests(0):
  656.         raise AssertionError
  657.     if not sw.do_I_have_requests(2):
  658.         raise AssertionError
  659.  
  660.  
  661. def test_last_piece_not_pre():
  662.     ds = DummyStorage(51, ranges = [
  663.         (50, 1)])
  664.     sw = StorageWrapper(ds, 2, [
  665.         sha('aa').digest()] * 25 + [
  666.         sha('b').digest()], 2, ds.finished, None)
  667.     for i in xrange(25):
  668.         if not sw.new_request(i) == (0, 2):
  669.             raise AssertionError
  670.     
  671.     if not sw.new_request(25) == (0, 1):
  672.         raise AssertionError
  673.     sw.piece_came_in(25, 0, 'b')
  674.     r = range(25)
  675.     shuffle(r)
  676.     for i in r:
  677.         sw.piece_came_in(i, 0, 'aa')
  678.     
  679.     if not ds.done:
  680.         raise AssertionError
  681.     if not ds.s == 'a' * 50 + 'b':
  682.         raise AssertionError
  683.  
  684.